# -*- coding: utf-8 -*-
# $ Time    :2022/6/30 9:40
# $ Author  :@柒筱暮
# $ GitHub  :https://github.com/Angie-co
# $ File    :components.py

import settings
import json
import requests
import jieba
import csv
from collections import Counter
from wordcloud import WordCloud
from PIL import Image
import numpy as np


"""
第一页：https://club.jd.com/comment/productPageComments.action?callback=fetchJSON_comment98&productId=100026667910&score=0&sortType=5&page={0}&pageSize=10&isShadowSku=0&fold=1
第二页：https://club.jd.com/comment/productPageComments.action?callback=fetchJSON_comment98&productId=100026667910&score=0&sortType=5&page={1}&pageSize=10&isShadowSku=0&rid=0&fold=1
"""


class CollectData(object):
    def __init__(self):
        self.url = settings.URL
        self.headers = settings.HEADERS
        self.params = settings.PARAMS

    def _turnPages(self, pages=settings.PAGES) -> dict:
        """
        修改参数，实现翻页
        :param pages: 请求的页数，默认settings里的10页
        :return: url参数
        """
        for page in range(pages):
            self.params["page"] = page
            yield self.params

    def _requestPage(self) -> str:
        """
        获取每一页商品信息
        :return: 响应数据
        """
        for param in self._turnPages():
            try:
                resp = requests.get(url=self.url, headers=self.headers, params=param, proxies=settings.PROXIES)
            except AttributeError:
                resp = requests.get(url=self.url, headers=self.headers, params=param)
            yield resp.text.replace("fetchJSON_comment98(", "").replace(");", "")

    @property
    def parseData(self) -> dict:
        """
        从json文件中提取数据
        :return: 包含每一条商品数据的字典，共五个字段
        """
        for p in self._requestPage():
            json_page = json.loads(p)
            contents = json_page["comments"]
            for content in contents:
                product_name = content["referenceName"]
                product_color, product_size = content["productColor"], content["productSize"]
                score, comment = content["score"], content["content"]
                yield {"product_name": product_name,
                       "product_color": product_color, "product_size": product_size,
                       "score": score, "comment": comment}


class CountKeyword(object):
    def __init__(self, datas):
        self.commentString = ""
        for data in datas:
            self.commentString += data["comment"]

    def removePunctuation(self) -> str:
        """
        去除标点符号、空格、换行
        :return:
        """
        word_list = []
        for word in self.commentString:
            if word in r"，。；：？！·、‘’“”（）\n ":
                continue
            else:
                word_list.append(word)
        new_string = "".join(word_list)
        return new_string

    def cutWord(self) -> str:
        words = jieba.cut(self.removePunctuation())
        return words

    def calculateWordfrequency(self) -> dict:
        """
        统计词频
        :return: 统计好的词频字典，但没排序
        """
        ranking = []
        article = self.cutWord()
        word_frequency = dict(Counter(article))
        for item in list(word_frequency.items()):
            if len(item[0]) == 1:
                continue
            else:
                ranking.append(item)
        return dict(ranking)

    def sortRank(self) -> dict:
        """
        对获取到的词频进行排序
        :return: 已排序的词频字典
        """
        sort_rank = []
        ranking = self.calculateWordfrequency()
        rank_item = list(ranking.items())
        date = list(ranking.values())
        date.sort(reverse=True)  # 对所以词频进行倒序
        for item in date:
            for rank_ in rank_item:  # 遍历，取值，如果词频为指定排序好的词频，加入到sort_rank
                if rank_[1] == item:
                    sort_rank.append(rank_)
                else:
                    continue
        return dict(sort_rank)

    def toCsv(self) -> None:
        with open("商品评论词频统计.csv", "w", encoding="utf-8", newline="") as f:
            words_list = []
            for word_tuple in self.sortRank().items():
                words_list.append({"关键字": word_tuple[0], "频次": word_tuple[1]})
            cw = csv.DictWriter(f, ["关键字", "频次"])
            cw.writeheader()
            cw.writerows(words_list)


class PaintingWordcloud(object):
    def __init__(self, rank: dict):
        self.word_count = settings.WORDCOUNT
        self.img_path = settings.IMG
        self.rank = rank

    def keyWords(self) -> list:
        words = self.rank.keys()
        return list(words)[0:self.word_count]

    def painting(self) -> None:
        image = Image.open(settings.BACKGROUND)  # 打开蒙版
        arr = np.array(image)  # 将蒙版转换成数值数组
        wc = WordCloud(font_path=settings.FONT_PATH, background_color=settings.COLOR, mask=arr)
        wc.generate(text=" ".join(self.keyWords()))
        wc.to_file(self.img_path)


if __name__ == '__main__':
    datas = CollectData().parseData
    c = CountKeyword(datas)
    c.toCsv()
    for i in datas:
        print(i)
    pw = PaintingWordcloud(c.sortRank())
    pw.painting()
